package com.example.lotterysystem.service.impl;

import cn.hutool.crypto.digest.DigestUtil;
import com.example.lotterysystem.common.errorcode.ServiceErrorCodeConstants;
import com.example.lotterysystem.common.exception.ServiceException;
import com.example.lotterysystem.common.utils.JWTUtil;
import com.example.lotterysystem.common.utils.RegexUtil;
import com.example.lotterysystem.controller.param.ShortMessageLoginParam;
import com.example.lotterysystem.controller.param.UserLoginParam;
import com.example.lotterysystem.controller.param.UserPasswordLoginParam;
import com.example.lotterysystem.controller.param.UserRegisterParam;
import com.example.lotterysystem.dao.dataobject.Encrypt;
import com.example.lotterysystem.dao.dataobject.UserDO;
import com.example.lotterysystem.dao.mapper.UserMapper;
import com.example.lotterysystem.service.UserService;
import com.example.lotterysystem.service.VerificationCodeeService;
import com.example.lotterysystem.service.dto.UserDTO;
import com.example.lotterysystem.service.dto.UserLoginDTO;
import com.example.lotterysystem.service.dto.UserRegisterDTO;
import com.example.lotterysystem.service.enums.UserIdentityEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service("userServiceImpl")
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private VerificationCodeeService verificationCodeeService;

    @Override
    public UserRegisterDTO register(UserRegisterParam param) {
//效验注册信息
        checkRegisterInfo(param);
//加密私密数据（构造dao层请求）
        UserDO userDO = new UserDO();
        userDO.setEmail(param.getMail());
        userDO.setPhoneNumber(new Encrypt(param.getPhoneNumber()));
        userDO.setIdentity(param.getIdentity());
        userDO.setUserName(param.getName());
        if (StringUtils.hasText(param.getPassword())){
            userDO.setPassword(DigestUtil.sha256Hex(param.getPassword()));
        }
        userMapper.insert(userDO);

UserRegisterDTO userRegisterDTO = new UserRegisterDTO();
userRegisterDTO.setUserId(userDO.getId());
return userRegisterDTO;

    }

    @Override
    public UserLoginDTO login(UserLoginParam param) {
        UserLoginDTO userLoginDTO=null;
        //类型检查和类型转换
        if(param instanceof UserPasswordLoginParam loginParam){
//密码登录
userLoginDTO=loginByUserPassword(loginParam);
        } else if (param instanceof ShortMessageLoginParam loginParam) {
//短信登录
            System.out.println("短信登录:"+param);
        userLoginDTO=loginByShortMessage(loginParam);
        }else {
            throw new ServiceException(ServiceErrorCodeConstants.LOGIN_INFO_NOT_EXIST);
        }

        return userLoginDTO;
    }

    @Override
    public List<UserDTO> findBaseUserInfo(UserIdentityEnum identity) {
        String identityString=null==identity?null: identity.name();
        //查表
        List<UserDO>userDOList=userMapper.selectUserListByIdentity(identityString);
        List<UserDTO>userDTOList=userDOList.stream()
        .map(userDO -> {
            UserDTO userDTO = new UserDTO();
         userDTO.setUserName(userDO.getUserName());
         userDTO.setIdentity(UserIdentityEnum.fromIdentity(userDO.getIdentity()));
         userDTO.setPhoneNumber(userDO.getPhoneNumber().getValue());
         userDTO.setEmail(userDO.getEmail());
         userDTO.setUserId(userDO.getId());
         return userDTO;
        }).collect(Collectors.toList());
        System.out.println(userDTOList);
        return userDTOList;
    }

    /**
     * 用户短信登录
     * @param param
     * @return
     */
    private UserLoginDTO loginByShortMessage(ShortMessageLoginParam param) {
if(!RegexUtil.checkMobile(param.getLoginMobile())){
    throw new ServiceException(ServiceErrorCodeConstants.PHONE_NUMBER_FORMAT_ERROR);
}
        UserDO userDO = userMapper.selectByPhoneNumber(new Encrypt(param.getLoginMobile()));

//效验返回结果是否为空
        if(userDO==null){
            throw new ServiceException(ServiceErrorCodeConstants.User_INFO_IS_EMPTY);
        }
        //效验身份
        if(StringUtils.hasText(param.getMandatoryIdentity())
                && !param.getMandatoryIdentity().equalsIgnoreCase(userDO.getIdentity())){
           throw new ServiceException(ServiceErrorCodeConstants.LOGIN_IDENTITY_ERROR);
        }
        String code=verificationCodeeService.getVerificationCode(param.getLoginMobile());
        if(!param.getVerificationCode().equals(code)){
            throw new ServiceException(ServiceErrorCodeConstants.LOGIN_VERIFICATION_CODE_ERROR);
        }
        //塞入返回值（JWT）
        Map<String, Object> claim =new HashMap<>();
        claim.put("id",userDO.getId());
        claim.put("identity",userDO.getIdentity());
        String token = JWTUtil.genJwt(claim);
        UserLoginDTO userLoginDTO = new UserLoginDTO();
        userLoginDTO.setToken(token);
        userLoginDTO.setIdentity(UserIdentityEnum.fromIdentity(userDO.getIdentity()));
        return userLoginDTO;
    }

    /**
     * 用户密码登录
     * @param param
     * @return
     */
    private UserLoginDTO loginByUserPassword(UserPasswordLoginParam param) {
        UserDO userDO=null;
        //判断手机登录还是邮箱登录
        if(RegexUtil.checkMail(param.getLoginName())){
            //邮箱登录
            // 根据邮箱查询用户表
            userDO=userMapper.selectByEmail(param.getLoginName());
        } else if (RegexUtil.checkMobile(param.getLoginName())) {
            //手机号登录
            //根据手机号查询用户表
            userDO=userMapper.selectByPhoneNumber(new Encrypt(param.getLoginName()));
        }else {
            throw new ServiceException(ServiceErrorCodeConstants.LOGIN_NOT_EXIST);
        }

        if(userDO==null){
            throw new ServiceException(ServiceErrorCodeConstants.User_INFO_IS_EMPTY);
        }else if (StringUtils.hasText(param.getMandatoryIdentity())
                && !param.getMandatoryIdentity().equalsIgnoreCase(userDO.getIdentity())){
            //强制身份登录，身份校验不通过
            throw new ServiceException(ServiceErrorCodeConstants.LOGIN_IDENTITY_ERROR);
        } else if (!DigestUtil.sha256Hex(param.getPassword()).equals(userDO.getPassword())) {
            //效验密码不通过
throw new ServiceException(ServiceErrorCodeConstants.LOGIN_PASSWORD_ERROR);
        }
        //塞入返回值（JWT）
        Map<String, Object> claim =new HashMap<>();
        claim.put("id",userDO.getId());
        claim.put("identity",userDO.getIdentity());
        String token = JWTUtil.genJwt(claim);

        UserLoginDTO userLoginDTO = new UserLoginDTO();
        userLoginDTO.setToken(token);
        userLoginDTO.setIdentity(UserIdentityEnum.fromIdentity(userDO.getIdentity()));

        return userLoginDTO;
    }

    /**
     * 用户注册
     * @param param
     */

    private void checkRegisterInfo(UserRegisterParam param) {
        if(null==param){
            throw new ServiceException(ServiceErrorCodeConstants.REGISTER_INFO_IS_EMPTY);
        }

        //校验邮箱格式
if(!RegexUtil.checkMail(param.getMail())){
    throw new ServiceException(ServiceErrorCodeConstants.MAIL_FORMAT_ERROR);
}

        //校验手机号格式
        if(!RegexUtil.checkMobile(param.getPhoneNumber())){
            throw new ServiceException(ServiceErrorCodeConstants.PHONE_NUMBER_FORMAT_ERROR);
        }

        //校验用户的身份信息
        if(UserIdentityEnum.fromIdentity(param.getIdentity())==null){
            throw new ServiceException(ServiceErrorCodeConstants.USER_IDENTITY_ERROR);
        }

        //校验管理员密码必填
        if(UserIdentityEnum.ADMIN.name().equalsIgnoreCase(param.getIdentity())
                && !StringUtils.hasText(param.getPassword())){
       throw new ServiceException(ServiceErrorCodeConstants.ADMIN_PASSWORD_IS_EMPTY);
        }

        //校验密码长度
if(StringUtils.hasText(param.getPassword())
        &&!RegexUtil.checkPassword(param.getPassword())){
    throw new ServiceException(ServiceErrorCodeConstants.PASSWORD_LENGTH_ERROR);
}

        //校验邮箱是否被使用
        if(checkMailUsed(param.getMail())){
            throw new ServiceException(ServiceErrorCodeConstants.MAIL_USED);
        }
        //校验手机号是否被使用
        if(checkPhoneNumberUsed(param.getPhoneNumber())) {
    throw new ServiceException(ServiceErrorCodeConstants.PHONE_NUMBER_USED);
        }

    }

    private boolean checkPhoneNumberUsed(String phoneNumber) {
int count=userMapper.countByPhoneNumber(new Encrypt(phoneNumber));
if(count>0){
    return true;
}
return false;
    }

    private boolean checkMailUsed(String mail) {
int count=userMapper.countByMail(mail);
if(count>0){
    return true;
}
return false;
    }
}
